package com.fingard.csp.common.io;


import java.io.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class FileHelper {

    public static boolean existFile(String p_filepath) {
        File tmpFile = new File(p_filepath);
        if (tmpFile.exists()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean deleteFileIfExists(String p_filepath) {
        File tmpFile = new File(p_filepath);
        if (tmpFile.exists()) {
            tmpFile.delete();
            return true;
        } else {
            return false;
        }
    }

    public static void deleteFile(File file){
        //判断文件不为null或文件目录存在
        if (file == null || !file.exists()){
            System.out.println("文件删除失败,请检查文件路径是否正确");
            return;
        }
        //取得这个目录下的所有子文件对象
        File[] files = file.listFiles();
        //遍历该目录下的文件对象
        for (File f: files){
            //打印文件名
            String name = file.getName();
            //判断子目录是否存在子目录,如果是文件则删除
            if (f.isDirectory()){
                deleteFile(f);
            }else {
                f.delete();
            }
        }
        //删除空文件夹  for循环已经把上一层节点的目录清空。
        file.delete();
    }


    /**
     * 删除文件夹，包括文件和所有子目录及文件
     */
    public static boolean deleteRecursive(String pPath) {
        File tmpFile = new File(pPath);
        if (tmpFile.exists()) {
            if (tmpFile.isFile()) {
                if (tmpFile.delete()) {
                    return true;
                }
            } else if (tmpFile.isDirectory()) {
                String[] lists = tmpFile.list();
                if (lists == null || lists.length == 0) {
                    if (tmpFile.delete()) {
                        return true;
                    }
                } else {
                    for (String list : lists) {
                        if (!deleteRecursive(pPath + File.separator + list)) {
                            return false;
                        }
                    }
                    if (tmpFile.delete()) {
                        return true;
                    }
                }
            }
        }
        return false;
    }


    public static byte[] readFileBytes(String p_filepath) {
        File tmpFile = new File(p_filepath);
        if (!tmpFile.exists()) {
            return null;
        }
        Long filelength = tmpFile.length();
        byte[] filecontent = new byte[filelength.intValue()];
        try {
            FileInputStream in = new FileInputStream(tmpFile);
            in.read(filecontent);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filecontent;
    }

    /**
     * 将byte数组写入文件
     *
     * @param path
     * @param fileName
     * @param content
     * @throws IOException
     */
    public static void writeFile(String path, String fileName, byte[] content)
            throws IOException {
        try {
            File f = new File(path);
            if (!f.exists()) {
                f.mkdirs();
            }
            FileOutputStream fos = new FileOutputStream(path + fileName);
            fos.write(content);
            fos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将byte数组写入文件
     *
     * @param filePath
     * @param content
     * @throws IOException
     */
    public static void writeBytesToFile(String filePath, byte[] content)
            throws IOException {
        FileOutputStream fos = null;
        try {
            File f = new File(filePath);
            File paf = f.getParentFile();
            if (paf != null && !paf.exists()) {
                paf.mkdirs();
            }
            fos = new FileOutputStream(f);
            fos.write(content);
            fos.close();
            fos = null;
        } catch (IOException e) {
            throw e;
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

    public static String readFileText(String p_filepath, String p_encoding) {
        File tmpFile = new File(p_filepath);
        if (!tmpFile.exists()) {
            return null;
        }
        Long filelength = tmpFile.length();
        byte[] filecontent = new byte[filelength.intValue()];
        try {
            FileInputStream in = new FileInputStream(tmpFile);
            in.read(filecontent);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            return new String(filecontent, p_encoding);
        } catch (UnsupportedEncodingException e) {
            System.err.println("The OS does not support " + p_encoding);
            e.printStackTrace();
            return null;
        }
    }

    public static String readToString(File p_file, String p_encoding) {
        Long filelength = p_file.length();
        byte[] filecontent = new byte[filelength.intValue()];
        try {
            FileInputStream in = new FileInputStream(p_file);
            in.read(filecontent);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            return new String(filecontent, p_encoding);
        } catch (UnsupportedEncodingException e) {
            System.err.println("The OS does not support " + p_encoding);
            e.printStackTrace();
            return null;
        }
    }

    public static void mkdir(String p_dir) {
        File tmpFile = new File(p_dir);
        if (!tmpFile.exists() && !tmpFile.isDirectory()) {
            tmpFile.mkdirs();
        }
    }

    public static void mkdirsIfNotExists(String pDir) {
        File tmpFile = new File(pDir);
        if (!tmpFile.exists()) {
            tmpFile.mkdirs();
        }
    }

    public static void writeFile(String p_filename, StringBuilder p_sb) throws Exception {
        File tmpFile = new File(p_filename);
        File parentDir = new File(tmpFile.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        if (!tmpFile.exists()) {
            tmpFile.createNewFile();
        }
        PrintWriter tmpWriter = new PrintWriter(new FileWriter(tmpFile), true);
        tmpWriter.print(p_sb.toString());
        tmpWriter.close();
    }

    public static void writeFile(String p_filename, String p_text, String p_charset) throws Exception {
        File tmpFile = new File(p_filename);
        File parentDir = new File(tmpFile.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        if (!tmpFile.exists()) {
            tmpFile.createNewFile();
        }
        PrintWriter tmpWriter = new PrintWriter(p_filename, p_charset);
        tmpWriter.print(p_text);
        tmpWriter.flush();
        tmpWriter.close();
    }

    public static void writeFile(File file, String p_text, String p_charset) throws Exception {
        File parentDir = new File(file.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        if (!file.exists()) {
            file.createNewFile();
        }
        PrintWriter tmpWriter = new PrintWriter(file, p_charset);
        tmpWriter.print(p_text);
        tmpWriter.flush();
        tmpWriter.close();
    }

    public static void appendFile(String p_filename, String p_text, String p_charset) throws Exception {
        File tmpFile = new File(p_filename);
        File parentDir = new File(tmpFile.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        if (!tmpFile.exists()) {
            tmpFile.createNewFile();
        }

        FileOutputStream fop = null;
        try {
            fop = new FileOutputStream(tmpFile, true);
            fop.write(p_text.getBytes(p_charset));
            fop.flush();
            fop.close();
            fop = null;
        } catch (Exception ex) {

        } finally {
            if (fop != null) {
                fop.close();
            }
        }
    }

    /**
     * 复制文件
     *
     * @throws IOException
     */
    public static void copyFile(File pSrcFile, File pDestFile) throws IOException {
        File parentDir = new File(pDestFile.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        FileInputStream inStream = null;
        FileOutputStream outStream = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            inStream = new FileInputStream(pSrcFile);
            outStream = new FileOutputStream(pDestFile);
            inChannel = inStream.getChannel();
            outChannel = outStream.getChannel();
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } catch (IOException e) {
            throw (e);
        } finally {
            try {
                if (inChannel != null) {
                    inChannel.close();
                }
                if (inStream != null) {
                    inStream.close();
                }
                if (outChannel != null) {
                    outChannel.close();
                }
                if (outStream != null) {
                    outStream.close();
                }
            } catch (IOException e) {
                throw (e);
            }
        }
    }

    /**
     * 复制文件，如果目标文件已经存在，则比较文件大小，大小不同则删除目标文件再复制
     */
    public static boolean copyFileWithCompare(File pSrcFile, String pDestFilePath) throws IOException {
        File destFile = new File(pDestFilePath);
        File parentDir = new File(destFile.getParent());
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        } else if (destFile.exists() && destFile.length() != pSrcFile.length()) {
            destFile.delete();
        }
        destFile = new File(pDestFilePath);
        if (!destFile.exists()) {
            FileInputStream inStream = null;
            FileOutputStream outStream = null;
            FileChannel inChannel = null;
            FileChannel outChannel = null;
            try {
                inStream = new FileInputStream(pSrcFile);
                outStream = new FileOutputStream(destFile);
                inChannel = inStream.getChannel();
                outChannel = outStream.getChannel();
                inChannel.transferTo(0, inChannel.size(), outChannel);
            } catch (IOException e) {
                throw (e);
            } finally {
                try {
                    if (inChannel != null) {
                        inChannel.close();
                    }
                    if (inStream != null) {
                        inStream.close();
                    }
                    if (outChannel != null) {
                        outChannel.close();
                    }
                    if (outStream != null) {
                        outStream.close();
                    }
                } catch (IOException e) {
                    throw (e);
                }
            }
        }
        return true;
    }

    public static byte[] toByteArray(String filename) throws IOException {

        File f = new File(filename);
        if (!f.exists()) {
            throw new FileNotFoundException(filename);
        }

        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(f));
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            bos.close();
        }
    }

    public static String[] listFiles(String p_filepath) {
        if (p_filepath != null && !"".equals(p_filepath)) {
            File tmpFile = new File(p_filepath);
            if (tmpFile.exists() && tmpFile.isDirectory()) {
                return tmpFile.list();
            }
        }
        return null;
    }

    //获取文件夹目录下所有文件名
    public static List<String> listFilesByModDate(String dirPath) {
        List<String> fileNames = new ArrayList<String>();
        File file = new File(dirPath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            Arrays.sort(files, new Comparator<File>() {
                @Override
                public int compare(File f1, File f2) {
                    long diff = f1.lastModified() - f2.lastModified();
                    if (diff > 0) {
                        return -1;
                    } else if (diff == 0) {
                        return 0;
                    } else {
                        return 1;//如果 if 中修改为 返回-1 同时此处修改为返回 1  排序就会是递减
                    }
                }

                @Override
                public boolean equals(Object obj) {
                    return true;
                }
            });

            for (int i = 0; i < files.length; i++) {
                fileNames.add(files[i].getName());
            }
        }
        return fileNames;
    }

    /**
     * 复制文件
     *
     * @throws IOException
     */
    public static boolean moveFile(File p_srcFile, File p_destFile) throws Exception {
        try {
            if (!p_destFile.getParentFile().exists()) {
                p_destFile.getParentFile().mkdirs();
            }
            copyFile(p_srcFile, p_destFile);
            if (p_srcFile.delete()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            if (p_destFile.exists()) {
                p_destFile.delete();
            }
            throw e;
        }

    }

    /**
     * 文件移动
     *
     * @param source 原地址
     * @param target 新地址
     * @return
     */
    public static boolean renameTo(String source, String target) {
        File sourceFile = new File(target);
        if (!sourceFile.getParentFile().exists()) {
            sourceFile.getParentFile().mkdirs();
        }
        if (sourceFile.exists()) {
            if (sourceFile.delete()) {
            } else {
                return false;
            }
        }
        boolean flag = new File(source).renameTo(new File(target));
        return flag;
    }

    /**
     * 复制文件
     *
     * @throws IOException
     */
    public static int copyFile(String p_srcFile, String p_destFile) throws IOException {
        try {
            File destFile = new File(p_destFile);
            if (destFile.exists()) {
                return 1;
            } else if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            copyFile(new File(p_srcFile), destFile);
            return 0;
        } catch (IOException e) {
            throw (e);
        }
    }

    /**
     * 重命名文件或文件夹
     */
    public static boolean renameFileOrDir(File pSrcFile, File pDestFile) {
        File parentFile = pDestFile.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            parentFile.mkdirs();
        }
        return pSrcFile.renameTo(pDestFile);
    }

    /**
     * 复制目录
     * @param fromDir
     * @param toDir
     * @throws IOException
     */
    public static void copyDir(String fromDir,String toDir) throws IOException{
        //创建目录的File对象
        File dirSouce = new File(fromDir);
        //判断源目录是不是一个目录
        if (!dirSouce.isDirectory()) {
            //如果不是目录那就不复制
            return;
        }
        //创建目标目录的File对象
        File destDir = new File(toDir);
        //如果目的目录不存在
        if(!destDir.exists()){
            //创建目的目录
            FileHelper.mkdirsIfNotExists(toDir);
        }
        //获取源目录下的File对象列表
        File[]files = dirSouce.listFiles();
        for (File file : files) {
            //拼接新的fromDir(fromFile)和toDir(toFile)的路径
            String strFrom = fromDir + File.separator + file.getName();
            String strTo = toDir + File.separator + file.getName();
            //判断File对象是目录还是文件
            //判断是否是目录
            if (file.isDirectory()) {
                //递归调用复制目录的方法
                copyDir(strFrom,strTo);
            }
            //判断是否是文件
            if (file.isFile()) {
                if(!FileHelper.existFile(strTo)) {
                    new File(strTo).createNewFile();
                }
                //递归调用复制文件的方法
                copyFiles(strFrom,strTo);
            }
        }
    }
    /**
     * 复制文件
     * @param fromFile
     * @param toFile
     * @throws IOException
     */
    public static void copyFiles(String fromFile,String toFile) throws IOException{
        //字节输入流——读取文件
        FileInputStream in = new FileInputStream(fromFile);
        //字节输出流——写入文件
        FileOutputStream out = new FileOutputStream(toFile);
        //把读取到的内容写入新文件
        //把字节数组设置大一些   1*1024*1024=1M
        byte[] bs = new byte[1*1024*1024];
        int count = 0;
        while((count = in.read(bs))!=-1){
            out.write(bs,0,count);
        }
        //关闭流
        in.close();
        out.flush();
        out.close();
    }
}
